﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using NUnit.Framework;
using NUnit.Framework.Syntax.CSharp;

namespace Hawkeye.Specs
{
    [TestFixture]
    public class TemplateEngine_specs : AssertionHelper
    {
        TemplateEngine engine;

        [SetUp]
        public void SetUp()
        {
            engine = new TemplateEngine();
        }

        [Test]
        public void No_placeholder_means_no_change()
        {
            string no_change = "no change";
            Assert.That(engine.Evaluate(no_change), Is.EqualTo(no_change));
        }

        [Test]
        public void No_placeholder_means_no_change_even_with_a_set_variable()
        {
            engine["olof"] = "hej";
            Expect(engine.Evaluate("hoho"), Is.EqualTo("hoho"));
        }

        [Test]
        public void One_variable_and_one_placeholder()
        {
            engine["olof"] = "hej";
            Expect(engine.Evaluate("hoho${olof}"), Is.EqualTo("hohohej"));
        }

        [Test]
        public void One_variable_two_placeholders_is_OK()
        {
            engine["olof"] = "123";
            Expect(engine.Evaluate("${olof}${olof}"), Is.EqualTo("123123"));
        }

        [Test, ExpectedException]
        public void A_placeholder_without_a_variable_throws_because_the_variable_is_not_defined()
        {
            engine.Evaluate("${olof}");
        }

        [Test]
        public void Two_variables_works()
        {
            engine["olof"] = "123";
            engine["simone"] = "456";
            Expect(engine.Evaluate("${olof}${simone}"), Is.EqualTo("123456"));
        }

        [Test]
        public void Mixing_multiple_variable_in_a_more_complex_string()
        {
            engine["olof"] = "123";
            engine["simone"] = "456";
            Expect(engine.Evaluate("abc${olof}def${simone}ghi${simone}"), Is.EqualTo("abc123def456ghi456"));
        }

        [Test]
        public void Nesting_placeholders()
        {
            engine["name"] = "Cenk";
            Expect(engine.Evaluate("Hello ${${name}}"), Is.EqualTo("Hello ${Cenk}"));
        }
    }

    internal class TemplateEngine
    {
        private readonly IDictionary<string, string> variables = new Dictionary<string, string>();

        public string this[string name]
        {
            set { variables[name] = value; }
        }

        public string Evaluate(string input)
        {
            foreach (var pair in variables)
                input = input.Replace("${" + pair.Key + "}", pair.Value);

            if(input.Contains("${"))
                throw new Exception();

            return input;
        }
    }
}